package com.funo.wcity.app.service.mail.receive;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeUtility;

import com.funo.wcity.app.service.mail.send.MailBean;
import com.funo.wcity.app.service.mail.send.MailSession;
import com.funo.wcity.app.utils.StringUtil;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPMessage;
import com.sun.mail.imap.IMAPStore;
import com.sun.mail.pop3.POP3Folder;
import com.sun.mail.pop3.POP3Store;

/**
 * 类说明：接收电子邮件
 * 
 * @author 作者: 李刚
 * @version 创建时间：2011-7-23 下午04:45:34
 */
@SuppressWarnings("all")
public class ReceiveMail {
	private IMAPStore imapStore;
	private POP3Store pop3Store;
	private IMAPFolder imapFolder;
	private POP3Folder pop3Folder;
	private boolean saveAttachments = false;// 是否保存附件
	private String attachmentName;// 附件的名称
	private String folderName;// 邮件夹名称
	private String path;// 附件保存的位置
	private String content;
	private StringBuffer filename = new StringBuffer();
	private String imap;		//imap协议
	private String pop;     	//pop协议
	private String smtp;    	//smtp协议
	private String username;	//用户名
	private String password;	//密码

	/**
	 * 初始化接收邮件的构造方法
	 * 
	 * @param 
	 * 		username
	 *            用户名
	 * @param 
	 * 		password
	 *            密码
	 * @param 
	 * 		smtp
	 * 			smtp协议
	 * @param
	 * 		imap
	 * 			imap协议
	 * @param
	 * 		pop
	 * 			pop协议
	 * @throws MessagingException
	 */
	public ReceiveMail(String username, String password,String smtp,String imap,String pop)
			throws MessagingException {
		this.username = username;
		this.password = password;
		this.smtp=smtp;
		this.imap=imap;
		this.pop=pop;
		connection();// 连接到邮件服务器
	}

	// 创建与服务器的连接
	private void connection() throws MessagingException {
		//imap协议连接邮件
		if(imap!=null){
			Session session = MailSession.getInstance(imap,smtp);
			imapStore = (IMAPStore) session.getStore();
			// 连接到邮件服务器
			imapStore.connect(session.getProperty("mail.store.host"), username,password);
		}else if(pop!=null){
			Session session = MailSession.getInstance(pop,smtp);
			pop3Store = (POP3Store) session.getStore();
			// 连接到邮件服务器
			pop3Store.connect(session.getProperty("mail.store.host"), username,password);
		}
	}

	/**
	 * IMAP协议，打开指定的收件夹folderName,model文件夹打开模式
	 * @param
	 * 		folderName
	 * 			邮件夹名称
	 * @param
	 * 		model
	 * 			类型
	 */
	public IMAPFolder openImapFolder(String folderName, int model)
			throws MessagingException {
		this.folderName = folderName;
		imapFolder = (IMAPFolder) imapStore.getFolder(folderName);
		if (imapFolder.exists())
			imapFolder.open(model);
		else {
			imapFolder.create(Folder.HOLDS_MESSAGES);
			imapFolder.open(model);
		}
		return imapFolder;
	}
	
	/**
	 * POP3协议，打开指定的收件夹folderName,model文件夹打开模式
	 * @param
	 * 		folderName
	 * 			邮件夹名称
	 * @param
	 * 		model
	 * 			类型
	 */
	public POP3Folder openPop3Folder(String folderName, int model)
			throws MessagingException {
		this.folderName = folderName;
		pop3Folder = (POP3Folder) imapStore.getFolder(folderName);
		if (pop3Folder.exists())
			pop3Folder.open(model);
		else {
			pop3Folder.create(Folder.HOLDS_MESSAGES);
			pop3Folder.open(model);
		}
		return pop3Folder;
	}
	/**
	 * imap协议，得到某个邮件夹下的所有邮件的UID
	 * 
	 * return long[]
	 */
	public long[] getImapMessageUIDs(IMAPFolder folder) throws MessagingException {
		long[] uids = new long[folder.getMessageCount()];
		Message[] messages = folder.getMessages();
		int length = messages.length;
		if (length > 0) {
			for (int i = 0; i < length; i++) {//
				uids[length - 1 - i] = folder.getUID(messages[i]);
			}
			return uids;
		}
		return null;
	}
	/**
	 * Imap协议，设置邮件基本信息(发送人、接收人、抄送、主题、大小、发送日期、标记、邮件id、邮件UID)
	 * 
	 * @throws Exception
	 */
	private MailBean setImapMailBean(IMAPMessage m) throws Exception {
		MailBean mail = new MailBean();
		mail.setSubject(m.getSubject());//标题
		mail.setMailDate(m.getSentDate());//时间
		mail.setFromAddress(decode(InternetAddress.toString(m.getFrom())));// 设置发件人
		mail.setToCc(decode(InternetAddress.toString(m.getRecipients(Message.RecipientType.CC))));//抄送人
		mail.setToAddress(decode(InternetAddress.toString(m.getRecipients(Message.RecipientType.TO))));//收件人
		mail.setMessageId(m.getMessageID());
		mail.setMailSize(m.getSize());
		mail.setMessageUid(imapFolder.getUID(m));
		mail.setFlags(setFlags(m));
		mail.setMailIp(getMailIp(m.getHeader("Received")[0]));
		return mail;
	}
	/**
	 * POP3协议，设置邮件基本信息(发送人、接收人、抄送、主题、大小、发送日期、标记、邮件UID)
	 * 
	 * @throws Exception
	 */
	public MailBean setPop3MailBean(Message m) throws Exception {
		MailBean mail = new MailBean();
		mail.setSubject(m.getSubject());//标题
		mail.setMailDate(m.getSentDate());//时间
		mail.setFromAddress(decode(InternetAddress.toString(m.getFrom())));// 设置发件人
		mail.setToCc(decode(InternetAddress.toString(m.getRecipients(Message.RecipientType.CC))));//抄送人
		mail.setToAddress(decode(InternetAddress.toString(m.getRecipients(Message.RecipientType.TO))));//收件人
		mail.setMailSize(m.getSize());
		mail.setMessageUid(imapFolder.getUID(m));
		mail.setMailIp(getMailIp(m.getHeader("Received")[0]));
		return mail;
	}
	// 封装邮件的标记
	private String setFlags(IMAPMessage m) throws MessagingException {
		Flags flags = m.getFlags();
		StringBuffer sb = new StringBuffer();
		Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
		for (int i = 0; i < sf.length; i++) {
			String s;
			Flags.Flag f = sf[i];
			if (f == Flags.Flag.ANSWERED)
				s = "Answered";
			else if (f == Flags.Flag.DELETED)
				s = "Deleted";
			else if (f == Flags.Flag.DRAFT)
				s = "Draft";
			else if (f == Flags.Flag.FLAGGED)
				s = "Flagged";
			else if (f == Flags.Flag.RECENT)
				s = "Recent";
			else if (f == Flags.Flag.SEEN)
				s = "Seen";
			else
				continue; // skip it
			sb.append(s);
			sb.append(',');
		}
		if (sb.length() > 0)
			sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}
	// 根据指定的uid找到邮件具体内容(不保存附件)
	public MailBean getMessageByUID(long uid) throws Exception {
		return getMessageByUID(uid, false, null, null);
	}

	// 根据指定的uid找到邮件具体内容
	public MailBean getMessageByUID(long uid, boolean saveAttachments,
			String attachmentName, String path) throws Exception {
		this.saveAttachments = saveAttachments;
		this.attachmentName = attachmentName;
		this.path = path;
		MailBean mailbean = new MailBean();
		IMAPMessage m = (IMAPMessage) imapFolder.getMessageByUID(uid);
		m.setFlag(Flags.Flag.SEEN, false);// 设置邮件为未读
		mailbean = setImapMailBean(m);
		clear();// 清空缓存附件名与正文信息信息
		dumpPart(m);
		setContent(mailbean);// 设置邮件正文和附件信息
		return mailbean;
	}

	// 清空附件信息和正文信息
	private void clear() {
		content="";
		filename.delete(0, filename.length());
	}

	// 设置邮件正文和附件信息
	private void setContent(MailBean mailbean)
			throws UnsupportedEncodingException {
		mailbean.setContent(content.toString());
		if (filename.length() > 0) {
			mailbean.setFileNames(filename.deleteCharAt(filename.length() - 1).toString());
		}
	}
	// 解码
	private String decode(String mailadd) throws UnsupportedEncodingException {
		if (mailadd != null && !"".equals(mailadd)) {
			return MimeUtility.decodeText(mailadd);
		} else
			return null;
	}
    //IMAP协议，保存附件
	public void createLocalImapFile(long uid, boolean saveAttachments,
			String attachmentName, String path) throws Exception {
		this.saveAttachments = saveAttachments;
		this.attachmentName = attachmentName;
		this.path = path;
		IMAPMessage m = (IMAPMessage) imapFolder.getMessageByUID(uid);
		clear();// 清空缓存附件名与正文信息信息
		dumpPart(m);
	}
   //POP3协议，保存附件
	public void createLocalPop3File(Message m, boolean saveAttachments,
			String attachmentName, String path) throws Exception {
		this.saveAttachments = saveAttachments;
		this.attachmentName = attachmentName;
		this.path = path;
		clear();// 清空缓存附件名与正文信息信息
		dumpPart(m);
	}
	// 遍历正文内容
	private void dumpPart(Part p) throws Exception {
		String fn = decode(p.getFileName());
		if (fn != null && fn.length() > 0)
			filename.append(fn).append(",");
		if (p.isMimeType("text/plain")) {
			if (!saveAttachments)
				content=(String) p.getContent();// 添加邮件内容
		} else if (p.isMimeType("multipart/*")) {
			Multipart mp = (Multipart) p.getContent();
			int count = mp.getCount();
			for (int i = 0; i < count; i++)
				dumpPart(mp.getBodyPart(i));// 循环遍历每个邮件体
		} else if (p.isMimeType("message/rfc822")) {
			dumpPart((Part) p.getContent());
		} else {
			if (!saveAttachments) {
				Object o = p.getContent();
				if (o instanceof String) { 
					content=(String)o;
				}
			}
		}
		if (saveAttachments && !p.isMimeType("multipart/*")) {
			String disp = p.getDisposition();
			if ("inline".equals(disp)|| "block".equals(disp) || disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT)) {
				if (fn != null && fn.equals(attachmentName)) {
					try {// 保存附件
						File saveFile = new File(path + "/" + fn);
						if (!saveFile.getParentFile().exists())
							saveFile.getParentFile().mkdirs();
						((MimeBodyPart) p).saveFile(saveFile);// 保存附件到指定的路径中
						return;
					} catch (IOException ex) {
						ex.printStackTrace();
					}
				}
			}
		}
	}
	/**
	 * 解析来源IP地址
	 */
	public String getMailIp(String info){
		String msg="";
		if(!StringUtil.isEmpty(info)){
			if(info.indexOf("(unknown")>-1){
				msg=info.substring(info.indexOf("(unknown")+10, info.indexOf("]",info.indexOf("(unknown")));
			}
		}
		return msg;
	}
}
